package com.game;  
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.game.R;

import android.content.Context;  
import android.content.res.Resources;  
import android.graphics.Bitmap;  
import android.graphics.Canvas;  
import android.graphics.Color;  
import android.graphics.Paint;  
import android.graphics.Point;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.util.Log;  
import android.view.KeyEvent;  
import android.view.MotionEvent;
import android.view.SurfaceHolder;  
import android.view.SurfaceView;  
import android.view.SurfaceHolder.Callback;  


public class MySurfaceView extends SurfaceView implements Callback, Runnable {  
    private Thread th = new Thread(this);  
    private SurfaceHolder sfh;  
    private int SH, SW;  
    private Canvas canvas;
    boolean quit = false;

	/**
	 * xCount x轴方向的图标数+1
	 * yCount y轴方向的图标数+1
	 * map 连连看游戏棋盘
	 * iconSize 图标大小
	 * iconCounts 图标的数目
	 */
	protected  static final int xCount =11;
	protected static final int  yCount =16;
	protected int[][] map = new int[xCount][yCount];
	protected int iconSize=30;
	protected int iconCounts=28;
	protected Bitmap[] icons=new Bitmap[iconCounts];
	
	/**
	 * path 可以连通点的路径
	 * selected 选中的图标
	 */
	private Point[] pathPoint = null;
	protected List<Point> selected = new ArrayList<Point>(); 
 

	/**
	 * mStatusText 
	 * gameState
	 */
	//private static TextView mStatusText;
	//private static TextView gameState;
	private static final int REFRESH_VIEW =1;
	private static final int UPDATE_TXT=2;
	
	public  static final int WIN=1;
	public static final int LOSE=2;
	public  static  int PAUSE=3;
	public static final int PLAY=4;
	
	private  int Help ;
	private  int TotalTime;
	private int LeaveTime;
	
	private static int mMode=PLAY;
	
	private List<Point> path = new ArrayList<Point>();
 
	private RefreshTime refreshTime = new RefreshTime();
	
    public MySurfaceView(Context context) {  
        super(context);  
        this.setKeepScreenOn(true);  
        sfh = this.getHolder();  
        sfh.addCallback(this);  
        setFocusable(true);  //备注1
		
		Resources r = getResources();
		loadBitmaps(1, r.getDrawable(R.drawable.i1));
		loadBitmaps(2, r.getDrawable(R.drawable.i2));
		loadBitmaps(3, r.getDrawable(R.drawable.i3));
		loadBitmaps(4, r.getDrawable(R.drawable.i4));
		loadBitmaps(5, r.getDrawable(R.drawable.i5));
		loadBitmaps(6, r.getDrawable(R.drawable.i6));
		loadBitmaps(7, r.getDrawable(R.drawable.i7));
		loadBitmaps(8, r.getDrawable(R.drawable.i8));
		loadBitmaps(9, r.getDrawable(R.drawable.i9));
		loadBitmaps(10, r.getDrawable(R.drawable.i10));
		loadBitmaps(11, r.getDrawable(R.drawable.i11));
		loadBitmaps(12, r.getDrawable(R.drawable.i12));
		loadBitmaps(13, r.getDrawable(R.drawable.i13));
		loadBitmaps(14, r.getDrawable(R.drawable.i14));
		loadBitmaps(15, r.getDrawable(R.drawable.i15));
		loadBitmaps(16, r.getDrawable(R.drawable.i16));
		loadBitmaps(17, r.getDrawable(R.drawable.i17));
		loadBitmaps(18, r.getDrawable(R.drawable.i18));
		loadBitmaps(19, r.getDrawable(R.drawable.i19));
		loadBitmaps(20, r.getDrawable(R.drawable.i20));
		loadBitmaps(21, r.getDrawable(R.drawable.i21));
		loadBitmaps(22, r.getDrawable(R.drawable.i22));
		loadBitmaps(23, r.getDrawable(R.drawable.i23));
		loadBitmaps(24, r.getDrawable(R.drawable.i24));
		loadBitmaps(25, r.getDrawable(R.drawable.i25));
		loadBitmaps(26, r.getDrawable(R.drawable.i26));
		loadBitmaps(27, r.getDrawable(R.drawable.i27));
		
		initNewGame();
		refreshTime.start();
	
    }  
    public void surfaceCreated(SurfaceHolder holder) {  
        SH = this.getHeight();  
        SW = this.getWidth();  
        th.start();  
    }  
    public void draw() {  
        canvas = sfh.lockCanvas();
        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        canvas.drawRect(0, 0, SW, SH, paint);   //备注2
        canvas.save();   //备注3
        //canvas.drawText("Himi", bmp_x-2, bmp_y-10, p2);  
        this.onDraw(canvas);
        canvas.restore();  //备注3
        sfh.unlockCanvasAndPost(canvas);  
    }  
    public void cycle() {  
 
    }  
  
    @Override  
    public void run() {  
        // TODO Auto-generated method stub  
        while (!quit) {  
            draw();  
            cycle();  
            try {  
                Thread.sleep(100);  
            } catch (Exception ex) {  
            }  
        }  
    }  
    @Override  
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
        // TODO Auto-generated method stub  
    }  
    @Override  
    public void surfaceDestroyed(SurfaceHolder holder) {  
        // TODO Auto-generated method stub  
    }

	/**
	 * 
	 * @param 特定图标的标识
	 * @param d drawable下的资源
	 */
	public void loadBitmaps(int key,Drawable d){
		Bitmap bitmap = Bitmap.createBitmap(iconSize,iconSize,Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmap);
		d.setBounds(0, 0, iconSize, iconSize);
		d.draw(canvas);
		icons[key]=bitmap;
	}
	
	/**
	 * 重载onDraw()方法
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		
		/**
		 * 绘制选中图标，当选中时图标背景是一个黄色的矩形
		 */
		for(Point position:selected){
			Paint paint = new Paint();
			paint.setColor(Color.YELLOW);
			paint.setStyle(Style.FILL);
			Point p = indextoScreen(position.x, position.y);
			canvas.drawRect(p.x, p.y, p.x + iconSize, p.y + iconSize, paint);
		}
		
		/**
		 * 绘制连通路径，然后将路径以及两个图标清除
		 */
		if (pathPoint != null && pathPoint.length >= 2) {
			for (int i = 0; i < pathPoint.length - 1; i++) {
				Paint paint = new Paint();
				paint.setARGB(255, 60, 60, 200);
				paint.setStyle(Paint.Style.STROKE);
				paint.setStrokeWidth(2);
				Point p1 = indextoScreen(pathPoint[i].x, pathPoint[i].y);
				Point p2 = indextoScreen(pathPoint[i + 1].x, pathPoint[i + 1].y);
				canvas.drawLine(p1.x + iconSize / 2, p1.y + iconSize / 2,
						p2.x + iconSize / 2, p2.y + iconSize / 2, paint);
			}
			Point p = pathPoint[0];
			map[p.x][p.y] = 0;
			p = pathPoint[pathPoint.length - 1];
			map[p.x][p.y] = 0;
			selected.clear();
			pathPoint = null;
		}
		/**
		 * 绘制棋盘的所有图标 当这个坐标内的值大于0时绘制
		 */
		for(int x=0;x<map.length;x+=1){
			for(int y=0;y<map[x].length;y+=1){
				if(map[x][y]>0){
					Point p = indextoScreen(x, y);
					canvas.drawBitmap(icons[map[x][y]], p.x,p.y,null);
				}
			}
		}
	}
	
	/**
	 * 
	 * @param path
	 */
	public void drawLine(Point[] path) {
		this.pathPoint = path;
		this.invalidate();
	}
	
	/**
	 * 工具方法
	 * @param x 数组中的横坐标
	 * @param y 数组中的纵坐标
	 * @return 将图标在数组中的坐标转成在屏幕上的真实坐标
	 */
	public Point indextoScreen(int x,int y){
		return new Point(x * iconSize , y * iconSize );
	}
	/**
	 * 工具方法
	 * @param x 屏幕中的横坐标
	 * @param y 屏幕中的纵坐标
	 * @return 将图标在屏幕中的坐标转成在数组上的虚拟坐标
	 */
	public Point screenToindex(int x,int y){
		return new Point(x/ iconSize , y / iconSize );
	}



	public  void initNewGame(){
		Help=10;
		TotalTime=10;
		LeaveTime=TotalTime;
		initMap();
		this.invalidate();
	}
	
	class RefreshHandler extends Handler{
		
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			if(msg.what==REFRESH_VIEW){
				Log.i("------->", "REFRESH_VIEW");
				invalidate();
				if (win()) {
					setMode(WIN);
				} else if (die()) {
					change();
				}
			}
			if(msg.what==UPDATE_TXT){
				//mStatusText.setText("剩余时间:"+LeaveTime+"   帮助次数:"+Help);
				//mStatusText.invalidate();
				Log.i("------->", "UpdateText()"+mMode);
				//Log.i("------->", mStatusText.getText().toString());
				if(LeaveTime<=0){
					setMode(LOSE);
				}
			}
		}
		public void sleep(int delayTime){
			this.removeMessages(0);
			Message message = new Message();
			message.what=REFRESH_VIEW;
			sendMessageDelayed(message, delayTime);
		
		}
	}
	
	class RefreshTime extends Thread{

		public void run() {
			while(LeaveTime>0){
				LeaveTime--;
				Message msg = new Message();
				msg.what = UPDATE_TXT;
				refreshHandler.sendMessage(msg);
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

	private RefreshHandler refreshHandler = new RefreshHandler();
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int x=(int) event.getX();
		int y=(int) event.getY();
		Point p= screenToindex(x, y);
		if (map[p.x][p.y] > 0) {
			if (selected.size() == 1) {
				if (link(selected.get(0), p)) {
					selected.add(p);
					drawLine(path.toArray(new Point[] {}));
					refreshHandler.sleep(500);
				} else {
					selected.clear();
					selected.add(p);
					this.invalidate();
				}
			} else {
				selected.add(p);
				this.invalidate();
			}

		}
		return super.onTouchEvent(event);
	}
	
	
	
	public void initMap(){
		int x = 1;
		int y = 0;
		for (int i = 1; i < xCount - 1; i++) {
			for (int j = 1; j < yCount - 1; j++) {
				map[i][j]=x;
				if (y == 1) {
					x++;
					y = 0;
					if (x == iconCounts ) {
						x = 1;
					}
				} else {
					y = 1;
				}
			}
		}
		change();
	}

	private void change() {
		Random random = new Random();
		int tmpV,tmpX,tmpY;
		for(int x=1;x<xCount-1;x++){
			for(int y=1;y<yCount-1;y++){
				tmpX=1+random.nextInt(xCount-2);
				tmpY=1+random.nextInt(yCount-2);
				tmpV=map[x][y];
				map[x][y]=map[tmpX][tmpY];
				map[tmpX][tmpY]=tmpV;
			}
		}
		if(die()){
			change(); 
		}
	}

	public static  void setMode(int newMode) {
		mMode=newMode;
		String str="";
		if(mMode==WIN){
			str="  真棒，恭喜过关.按上继续";
			//gameState.setVisibility(VISIBLE);
		}else if(mMode==PLAY){
			//gameState.setVisibility(INVISIBLE);
		}else if(mMode==LOSE){
			str="  很遗憾，时间到了.按上继续";
			//gameState.setVisibility(VISIBLE);
		}
		//gameState.setText(str);
	}
	private boolean die() {
		for (int y = 1; y < yCount - 1; y++) {
			for (int x = 1; x < xCount - 1; x++) {
				if (map[x][y] != 0) {
					for (int j = y; j < yCount - 1; j++) {
						if (j == y) {
							for (int i = x + 1; i < xCount - 1; i++) {
								if (map[i][j] == map[x][y]
										&& link(new Point(x, y),
												new Point(i, j))) {
									return false;
								}
							}
						} else {
							for (int i = 1; i < xCount - 1; i++) {
								if (map[i][j] == map[x][y]
										&& link(new Point(x, y),
												new Point(i, j))) {
									return false;
								}
							}
						}
					}
				}
			}
		}
		return true;
	}
	
	List<Point> p1E = new ArrayList<Point>();
	List<Point> p2E = new ArrayList<Point>();
	
	private boolean link(Point p1, Point p2) {
		if (p1.equals(p2)) {
			return false;
		}
		path.clear();
		if(map[p1.x][p1.y]==map[p2.x][p2.y]){
			if(linkD(p1, p2)){
				path.add(p1);
				path.add(p2);
				return true;
			}
			
			Point p = new Point(p1.x, p2.y);
			if (map[p.x][p.y] == 0) {
				if (linkD(p1, p) && linkD(p, p2)) {
					path.add(p1);
					path.add(p);
					path.add(p2);
					return true;
				}
			}
			p = new Point(p2.x, p1.y);
			if (map[p.x][p.y] == 0) {
				if (linkD(p1, p) && linkD(p, p2)) {
					path.add(p1);
					path.add(p);
					path.add(p2);
					return true;
				}
			}
			expandX(p1, p1E);
			expandX(p2, p2E);
			
			for(Point pt1:p1E){
				for(Point pt2:p2E){
					if(pt1.x==pt2.x){
						if(linkD(pt1, pt2)){
							path.add(p1);
							path.add(pt1);
							path.add(pt2);
							path.add(p2);
							return true;
						}
					}
				}
			}
			
			expandY(p1, p1E);
			expandY(p2, p2E);
			for(Point pt1:p1E){
				for(Point pt2:p2E){
					if(pt1.y==pt2.y){
						if(linkD(pt1, pt2)){
							path.add(p1);
							path.add(pt1);
							path.add(pt2);
							path.add(p2);
							return true;
						}
					}
				}
			}
			return false;
		}
		return false;
	}
	
	private boolean linkD(Point p1, Point p2) {
		if (p1.x == p2.x) {
			int y1 = Math.min(p1.y, p2.y);
			int y2 = Math.max(p1.y, p2.y);
			boolean flag = true;
			for (int y = y1 + 1; y < y2; y++) {
				if (map[p1.x][y] != 0) {
					flag = false;
					break;
				}
			}
			if (flag) {
				return true;
			}
		}
		if (p1.y == p2.y) {
			int x1 = Math.min(p1.x, p2.x);
			int x2 = Math.max(p1.x, p2.x);
			boolean flag = true;
			for (int x = x1 + 1; x < x2; x++) {
				if (map[x][p1.y] != 0) {
					flag = false;
					break;
				}
			}
			if (flag) {
				return true;
			}
		}
		return false;
	}
	
	private void expandX(Point p,List<Point> l){
		l.clear();
		for(int x=p.x+1;x<xCount;x++){
			if(map[x][p.y]!=0){
				break;
			}
			l.add(new Point(x,p.y));
		}
		for(int x=p.x-1;x>=0;x--){
			if(map[x][p.y]!=0){
				break;
			}
			l.add(new Point(x,p.y));
		}
	}
	
	private void expandY(Point p,List<Point> l){
		l.clear();
		for(int y=p.y+1;y<yCount;y++){
			if(map[p.x][y]!=0){
				break;
			}
			l.add(new Point(p.x,y));
		}
		for(int y=p.y-1;y>=0;y--){
			if(map[p.x][y]!=0){
				break; 
			} 
			l.add(new Point(p.x,y));
		}
	} 
	private boolean win(){
		for(int x=0;x<xCount;x++){
			for(int y=0;y<yCount;y++){
				if(map[x][y]!=0){
					return false;
				}
			}
		}
		return true;
	}
	private void autoClear(){
		if(Help==0){
			//return;
		}
		Help--;
		Message msg = new Message();
		msg.what = UPDATE_TXT;
		refreshHandler.sendMessage(msg);
		drawLine(path.toArray(new Point[] {}));
		refreshHandler.sleep(500);
	}

	public void onKeyDown(int keyCode) {
		if (keyCode == KeyEvent.KEYCODE_MENU) {
			Log.i("------->", "KEYCODE_MENU");
			autoClear();
		} else if (keyCode == KeyEvent.KEYCODE_HOME) {
			Log.i("------->", "KEYCODE_HOME");
			initNewGame();
			setMode(PLAY);
		} else if (keyCode == KeyEvent.KEYCODE_BACK) {
			quit = true;
		}
	}
}  